package cn.llyong.rpc.server.netty;

import cn.llyong.rpc.common.config.MonkeyRpcProperties;
import cn.llyong.rpc.common.exception.RpcException;
import cn.llyong.rpc.server.handler.RpcServerHandler;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.*;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import io.netty.handler.logging.LogLevel;
import io.netty.handler.logging.LoggingHandler;
import io.netty.handler.timeout.IdleStateHandler;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.DisposableBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.annotation.Autowired;


/**
 * @description:
 * @author: lvyong
 * @date: 2020年06月24日 09:25
 */
public class RpcServer implements InitializingBean, DisposableBean {

    private final Logger logger = LoggerFactory.getLogger(this.getClass());

    private static final EventLoopGroup bossGroup = new NioEventLoopGroup(1);
    private static final EventLoopGroup workerGroup = new NioEventLoopGroup(4);

    @Autowired
    private MonkeyRpcProperties rpcProperties;

    @Override
    public void afterPropertiesSet() throws Exception {
        ServerBootstrap b = new ServerBootstrap();
        b.group(bossGroup,workerGroup).
                channel(NioServerSocketChannel.class)
                .handler(new LoggingHandler(LogLevel.DEBUG))
                .option(ChannelOption.SO_BACKLOG,1024)
                .childOption(ChannelOption.SO_KEEPALIVE,true)
                .childOption(ChannelOption.TCP_NODELAY,true)
                .childHandler(new ChannelInitializer<SocketChannel>() {
                    //创建NIOSocketChannel成功后，在进行初始化时，将它的ChannelHandler设置到ChannelPipeline中，用于处理网络IO事件
                    @Override
                    protected void initChannel(SocketChannel channel) throws Exception {
                        ChannelPipeline pipeline = channel.pipeline();
                        pipeline.addLast(new IdleStateHandler(0, 0, 60));
//                        pipeline.addLast(new JSONEncoder());
//                        pipeline.addLast(new JSONDecoder());
//                        pipeline.addLast(new RpcRequestHandler());
                        pipeline.addLast(new RpcServerHandler());
                    }
                });
        try {

            String serverPort = rpcProperties.getServerPort();
            ChannelFuture future = b.bind(Integer.parseInt(serverPort)).sync();
            logger.info("rpc server 启动监听端口： 【{}】", serverPort);

            //不要加这句代码，否则会造成主线程一直处于阻塞状态
//            future.channel().closeFuture().sync();
        } catch (RpcException e) {
            throw e;
        } catch (Exception e) {
            throw new RpcException("rpc server init fail!!!", e);
        }
    }

    @Override
    public void destroy() throws Exception {
        bossGroup.shutdownGracefully();
        workerGroup.shutdownGracefully();
    }
}
